#include "hash_table.h"
#include <stdlib.h>
#include "linked_list.h"
#include <stdio.h>
#include <string.h>

int mainH() {
    int i;
    hash_table *tbl = create_table(7);
    for(i = 0; i < 50; i++)
        tbl_insert(&tbl, i, i % 9);
    
    //for(i = 0; i < 50; i++)
     //   printf("%d\n", tbl_get(tbl, i));
    tbl_print(tbl);
    printf("Size: %d\n", tbl -> size);
    printf("Load: %d\n", tbl -> load);
    
    return 0;
}

hash_table *create_table(int size) {
    hash_table *tbl = 0;
    if(tbl = malloc(sizeof(hash_table))) {
        tbl -> table = malloc(sizeof(llist) * size);
        memset(tbl -> table, 0, sizeof(llist) * size);
        tbl -> size = size;
        tbl -> load = 0;
    }
    return tbl;
}

int hash(hash_table *tbl, int val) {
    return val % tbl -> size;
}

void tbl_insert(hash_table **tblptr, int tid, int color) {
    hash_table *tbl = *tblptr;
    pair *new = malloc(sizeof(pair));
    new -> tid = tid;
    new -> color = color;
    int index = hash(tbl, tid);
    if(!tbl -> table[index]) 
        tbl -> table[index] = create_list();
    enqueue(tbl -> table[index], (void *)new);
    tbl -> load++;
    if(tbl -> load / (double) tbl -> size > 1.1)
        *tblptr = regrow(tbl);
}

hash_table *regrow(hash_table *tbl) {
    hash_table *new = create_table(tbl -> size * 2 + 1);
    int i;
    node *probe;
    node *prev;
    for(i = 0; i < tbl -> size; i++) 
        if(tbl -> table[i]) {
            probe = tbl -> table[i] -> head;
            while(probe) {
                tbl_insert(&new, ((pair *)(probe -> data)) -> tid, ((pair *)(probe -> data)) -> color);
                prev = probe;
                probe = probe -> next;
                free(prev -> data);
                free(prev);
            }
            free(tbl -> table[i]);
        }
    free(tbl);
    return new;
}

int tbl_get(hash_table *tbl, int tid) {
    int index = hash(tbl, tid);
    if(!tbl -> table[index])
        return 0;
    node *probe = tbl -> table[index] -> head;
    while(probe) {
        if(((pair *)(probe -> data)) -> tid == tid)
            return ((pair *)probe -> data) -> color;
        probe = probe -> next;
    }
    return 0;
    
}

void tbl_print(hash_table *tbl) {
    int i;
    node *probe;
    for(i = 0; i < tbl -> size; i++) {
        printf("Index %d:\n", i);
        if(tbl -> table[i]) {
            probe = tbl -> table[i] -> head;
            while(probe) {
                printf("tid: %d, color: %d\n", ((pair *)probe -> data) -> tid, ((pair *)probe -> data) -> color);
                probe = probe -> next;
            }
        }
    }
}
